/*
 * COPYRIGHT(c) SK telecom 2009
 * This software is the proprietary information of SK telecom.
 *
 * Revision History
 * Author       Date            Description
 * --------     ----------      ------------------
 * ?            ?               ?
 * nefer        2009.12.08      move to omp_common, modify pom.xml dependency httpclient
 *
 */
package com.tistory.commons.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.Hashtable;

import javax.net.ssl.HttpsURLConnection;

/**
 * HTTP URL에 해당하는 내용을 조회한다.
 * <P>
 *  Example :
 *  <pre>
 *  String url = "http://www.nate.com/index.html";
 *  Hashtable param = new Hashtable();
 *  param.put("category", "9");
 *  param.put("page", "1");
 *  HTTPContent hc = new HTTPContent(url, param);
 * </pre>
 */
public class HTTPUtil
{
    private URL url;
    private Hashtable param;
    private String encoding = "KSC_5601";
    private String methodType = "GET";
    private String bodyData = "";

    /**
     * URL을 이용하여 HTTPContent를 생성한다.
     * 
     * @param urlString 요청할 URL
     * @throws Exception
     */
    public HTTPUtil(String urlString) throws Exception
    {
        url = new URL(urlString);
    }

    public HTTPUtil(String urlString, String method) throws Exception{
        this(urlString);
        this.methodType = method;
    }

    /**
     * URL과 Request GET Parameter를 이용하여 HTTPContent를 생성한다.
     * 
     * @param urlString 요청할 URL
     * @param param Request Parameter
     * @throws Exception
     */
    public HTTPUtil(String urlString, Hashtable param) throws Exception
    {
        this(urlString);
        setParameter(param);
    }
    
    public HTTPUtil(String urlString, String method, Hashtable param) throws Exception
    {
        this(urlString,param);
        this.methodType = method;
    }
    
    public HTTPUtil(String urlString, String method, String bodyData) throws Exception
    {
        this(urlString);
        this.methodType = method;
        this.bodyData = bodyData;
    }

    /**
     * HTTP Request Parameter를 설정한다.
     * 
     * @param param HTTP Request Parameter
     */
    public void setParameter(Hashtable param)
    {
        this.param = param;
    }

    /**
     * Encoding을 설정한다. Encoding을 설정하지 않는 경우 기본 encoding("KSC_5601")이 사용된다.
     * 
     * @param encoding Character encoding
     */
    public void setEncoding(String encoding)
    {
        this.encoding = encoding;
    }
    
    public String getContent() throws Exception
    {
        return getStringContent();
    }
    
    public String getContent(int time) throws Exception
    {
        return getStringContent(time);
    }
    
    public Object getObjectContent() throws Exception{
        Object obj = null;
        HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
        urlConn.setRequestMethod(methodType);
        if (param != null)
        {
            urlConn.setDoOutput(true);
            OutputStream out = urlConn.getOutputStream();
            Writer writer = new OutputStreamWriter(out, encoding);
            
            Enumeration keys = param.keys();
            int i = 0;
            String key = null;
            
            while (keys.hasMoreElements())
            {
                if (++i > 1)
                    writer.write("&");

                key = (String) keys.nextElement();
                writer.write(key + "=" + URLEncoder.encode((String)param.get(key), encoding));
            }
            
            writer.close();
        }

        InputStream in = urlConn.getInputStream();
        ObjectInputStream is = new ObjectInputStream(in);
        obj = is.readObject();
        urlConn.disconnect();
        if (urlConn.getResponseCode() >= 400)
            throw new Exception(Integer.toString(urlConn.getResponseCode()));

        return obj;     
    }
    
    /**
     * URL Request에 대한 응답 내용을 리턴한다.
     * 
     * @return URL Request에 대한 응답 내용
     * @throws Exception
     */

    public String getStringContent(int time) throws Exception{
            
        HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
        urlConn.setRequestMethod(methodType);       
        if (param != null)
        {
            urlConn.setDoOutput(true);
            urlConn.setConnectTimeout(time);  //통합회원 일괄탈퇴시 오래걸림
            OutputStream out = urlConn.getOutputStream();
            Writer writer = new OutputStreamWriter(out, encoding);
            
            Enumeration keys = param.keys();
            int i = 0;
            String key = null;
            
            while (keys.hasMoreElements())
            {
                if (++i > 1)
                    writer.write("&");

                key = (String) keys.nextElement();
                writer.write(key + "=" + URLEncoder.encode((String)param.get(key), encoding));
            }
            
            writer.close();
        }

        InputStream in = urlConn.getInputStream();
        Reader reader = new InputStreamReader(in, encoding);
        BufferedReader br = new BufferedReader(reader);
        StringBuffer sbContent = new StringBuffer(1024);
        String data = null;
        int i = 0;

        while ((data = br.readLine()) != null)
        {
            if (++i > 1)
                sbContent.append("\n");
                
            sbContent.append(data);
        }

        br.close();
        urlConn.disconnect();
        
        if (urlConn.getResponseCode() >= 400)
            throw new Exception(Integer.toString(urlConn.getResponseCode()));

        return sbContent.toString();
    }
    
    public String getStringContent() throws Exception{
        
        HttpURLConnection urlConn = (HttpURLConnection)url.openConnection();
        urlConn.setRequestMethod(methodType);       
        if (param != null)
        {
            urlConn.setDoOutput(true);
            urlConn.setConnectTimeout(3000);
            OutputStream out = urlConn.getOutputStream();
            Writer writer = new OutputStreamWriter(out, encoding);
            
            Enumeration keys = param.keys();
            int i = 0;
            String key = null;
            
            while (keys.hasMoreElements())
            {
                if (++i > 1)
                    writer.write("&");

                key = (String) keys.nextElement();
                writer.write(key + "=" + URLEncoder.encode((String)param.get(key), encoding));
            }
            
            writer.close();
        }

        InputStream in = urlConn.getInputStream();
        Reader reader = new InputStreamReader(in, encoding);
        BufferedReader br = new BufferedReader(reader);
        StringBuffer sbContent = new StringBuffer(1024);
        String data = null;
        int i = 0;

        while ((data = br.readLine()) != null)
        {
            if (++i > 1)
                sbContent.append("\n");
                
            sbContent.append(data);
        }

        br.close();
        urlConn.disconnect();
        
        if (urlConn.getResponseCode() >= 400)
            throw new Exception(Integer.toString(urlConn.getResponseCode()));

        return sbContent.toString();
    }
    
    
    public String getContentHttps() throws Exception
    {
        return getStringContentHttps();
    }
    
    public Object getObjectContentHttps() throws Exception{
        Object obj = null;
        HttpsURLConnection urlConn = (HttpsURLConnection)url.openConnection();
        urlConn.setRequestMethod(methodType);
       
        if (param != null)
        {
            urlConn.setDoOutput(true);
            OutputStream out = urlConn.getOutputStream();
            Writer writer = new OutputStreamWriter(out, encoding);
            
            Enumeration keys = param.keys();
            int i = 0;
            String key = null;
            
            while (keys.hasMoreElements())
            {
                if (++i > 1)
                    writer.write("&");

                key = (String) keys.nextElement();
                writer.write(key + "=" + URLEncoder.encode((String)param.get(key), encoding));
            }
            
            writer.close();
        }

        InputStream in = urlConn.getInputStream();
        ObjectInputStream is = new ObjectInputStream(in);
        obj = is.readObject();
        urlConn.disconnect();
        
        int code = urlConn.getResponseCode();
        String redtUrl = urlConn.getHeaderField("Location");
        
        if (code >= 400)
            throw new Exception(Integer.toString(urlConn.getResponseCode()));
                
//        if(redtUrl != null && mustRedirect(code))
////            ServletActionContext.getResponse().sendRedirect(redtUrl);

        return obj;     
    }
    
    /**
     * URL Request에 대한 응답 내용을 리턴한다.
     * 
     * @return URL Request에 대한 응답 내용
     * @throws Exception
     */

    public String getStringContentHttps() throws Exception{
        HttpsURLConnection urlConn = (HttpsURLConnection)url.openConnection();
        urlConn.setRequestMethod(methodType);  
        
        if (param != null)
        {
            urlConn.setDoOutput(true);
            OutputStream out = urlConn.getOutputStream();
            Writer writer = new OutputStreamWriter(out, encoding);
            
            Enumeration keys = param.keys();
            int i = 0;
            String key = null;
            
            while (keys.hasMoreElements())
            {
                if (++i > 1)
                    writer.write("&");

                key = (String) keys.nextElement();
                writer.write(key + "=" + URLEncoder.encode((String)param.get(key), encoding));
            }
            
            writer.close();
        }
        
        InputStream in = urlConn.getInputStream();
        Reader reader = new InputStreamReader(in, encoding);
        BufferedReader br = new BufferedReader(reader);
        StringBuffer sbContent = new StringBuffer(1024);
        String data = null;
        int i = 0;

        while ((data = br.readLine()) != null)
        {
            if (++i > 1)
                sbContent.append("\n");
                
            sbContent.append(data);
        }

        br.close();
        urlConn.disconnect();
        
        int code = urlConn.getResponseCode();
        String redtUrl = urlConn.getHeaderField("Location");
        
        if (code >= 400)
            throw new Exception(Integer.toString(urlConn.getResponseCode()));
                
//        if(redtUrl != null && mustRedirect(code))
//            ServletActionContext.getResponse().sendRedirect(redtUrl);

        return sbContent.toString();
    }

    
    private boolean mustRedirect(int code){
        if (code == HttpURLConnection.HTTP_MOVED_PERM ||
            code == HttpURLConnection.HTTP_MOVED_TEMP)  {
             return true;
        } else return false;
     }

    


    /**
     * HTML문자열을 분석하여 input type이 text에 해당하는 파라미터 정보를 리턴한다.
     * 
     * @param html HTML String
     * @return Hashtable
     */
    public static Hashtable getHtmlInputParameter(String html) throws Exception
    {
        int startTag = -1;
        int endTag = -1;
        Hashtable param = new Hashtable();
        
        String inputTag = null;
        String name = null;
        String value = null;
        int startPos;
        int endPos;
        
        while ((startTag = html.indexOf("<input type=\"text\" ", endTag)) != -1)
        {
            endTag = html.indexOf(">", startTag + 19);
            if (endTag == -1)
                break;
                
            inputTag = html.substring(startTag + 19, endTag);
            
            // find "name" position
            startPos = inputTag.indexOf("name=\"");
            endPos = inputTag.indexOf("\"", startPos + 6);
            name = inputTag.substring(startPos + 6, endPos);
            
            // find "value" position
            startPos = inputTag.indexOf("value=\"", endPos);
            endPos = inputTag.indexOf("\"", startPos + 7);
            value = inputTag.substring(startPos + 7, endPos);
            
            param.put(name, value);
        }
        
        return param;
    }
    
    
    /**
     * b
     * @param body
     * @return
     * @throws Exception
     */
    public String sendResponseBody() throws Exception {
//        
        String result   = "";
//        String protocol = "";
//        String host     = "";
//        int    port     = 0;
//        String path     = "";        
//
//        //URL url = new URL(urlInfo);
//        protocol = url.getProtocol();
//        host     = url.getHost();
//        port     = url.getPort() == -1 ? url.getDefaultPort() : url.getPort();
//        path     = url.getPath();
//        
//        HttpClient client = null;
//        PostMethod post   = null;
//        
//        try {
//            client = new HttpClient();
//
//            client.getHostConfiguration().setHost(host, port, protocol);
//            client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);            
//
//            // Connection TIME OUT 10 초 
//            // Read       TIME OUT  5 초
//            client.setConnectionTimeout(10000);            
//            client.setTimeout(5000);
//            
//            post = new PostMethod(path);
//            post.addRequestHeader("Content-Type","text/xml; charset=euc-kr");
//            post.addRequestHeader("Host", "");
//            post.addRequestHeader("Content-Length", bodyData.getBytes("euc-kr").length + "");
//            post.addRequestHeader("Connection", "close");
//            post.setRequestBody(bodyData);            
//            client.executeMethod(post);
//       
//            InputStream    is = post.getResponseBodyAsStream();            
//            BufferedReader br = new BufferedReader(new InputStreamReader(is, "euc-kr"));
//            
//            String line = null;
//            StringBuffer buf = new StringBuffer();
//            while ((line = br.readLine()) != null) {
//              buf.append(line + "\n");
//            }
//            
//            result = buf.toString();
//
//            if ( br!=null ) try{ br.close(); } catch(Exception e){e.printStackTrace();}
//            if ( is!=null ) try{ is.close(); } catch(Exception e){e.printStackTrace();}
//
//        } catch (HttpException e) {
//            throw new Exception(e);
//        } catch (IOException e) {
//            throw new Exception(e);
//        } catch (Throwable t) {
//            throw new Exception(t);
//        } finally {
//            if (post != null)
//                post.releaseConnection();
//        }           
        return result;
    }
    
    /**
     * b
     * @param body
     * @return
     * @throws Exception
     */
    public String sendResponseBody(String charSet) throws Exception {
        
        String result   = "";
//        String protocol = "";
//        String host     = "";
//        int    port     = 0;
//        String path     = "";        
//
//        //URL url = new URL(urlInfo);
//        protocol = url.getProtocol();
//        host     = url.getHost();
//        port     = url.getPort() == -1 ? url.getDefaultPort() : url.getPort();
//        path     = url.getPath();
//        
//        HttpClient client = null;
//        PostMethod post   = null;
//        
//        try {
//            client = new HttpClient();
//
//            client.getHostConfiguration().setHost(host, port, protocol);
//            client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);            
//
//            // Connection TIME OUT 10 초 
//            // Read       TIME OUT  5 초
//            client.setConnectionTimeout(10000);            
//            client.setTimeout(5000);
//            
//            post = new PostMethod(path);
//            post.addRequestHeader("Content-Type","text/xml; charset=" + charSet);
//            post.addRequestHeader("Host", "");
//            post.addRequestHeader("Content-Length", bodyData.getBytes(charSet).length + "");
//            post.addRequestHeader("Connection", "close");
//            post.setRequestBody(bodyData);            
//            client.executeMethod(post);
//       
//            InputStream    is = post.getResponseBodyAsStream();            
//            BufferedReader br = new BufferedReader(new InputStreamReader(is, charSet));
//            
//            String line = null;
//            StringBuffer buf = new StringBuffer();
//            while ((line = br.readLine()) != null) {
//              buf.append(line + "\n");
//            }
//            
//            result = buf.toString();
//
//            if ( br!=null ) try{ br.close(); } catch(Exception e){e.printStackTrace();}
//            if ( is!=null ) try{ is.close(); } catch(Exception e){e.printStackTrace();}
//
//        } catch (HttpException e) {
//            throw new Exception(e);
//        } catch (IOException e) {
//            throw new Exception(e);
//        } catch (Throwable t) {
//            throw new Exception(t);
//        } finally {
//            if (post != null)
//                post.releaseConnection();
//        }           
        return result;
    }

}
